/**
 * Author(s): xuming.Wong <xuming.Wong@gmail.com>
 */

#ifndef __PQ_MaterialManager_H__
#define __PQ_MaterialManager_H__

#include "EnginePrerequisites.h"

#include "OgreMaterialManager.h"
#include "OgreMaterialSerializer.h"
#include "OgreResource.h"
#include "OgreTechnique.h"
#include "OgrePass.h"
#include "OgreTextureManager.h"
#include "OgreScriptCompiler.h"

namespace PQEngine
{
	/*see Ogre::ScriptCompilerListener,we use this to parse material script
	*/
	class GPKMaterialCompilerListener:
		public Ogre::ScriptCompilerListener
	{
	public:
		GPKMaterialCompilerListener(Ogre::String materialPath);
		~GPKMaterialCompilerListener();

		virtual Ogre::ConcreteNodeListPtr importFile(Ogre::ScriptCompiler *compiler, const Ogre::String &name);
		
		virtual void preConversion(Ogre::ScriptCompiler *compiler, Ogre::ConcreteNodeListPtr nodes);
		
		virtual bool postConversion(Ogre::ScriptCompiler *compiler, const Ogre::AbstractNodeListPtr&);

		virtual void handleError(Ogre::ScriptCompiler *compiler, unsigned int code, const Ogre::String &file, int line, const Ogre::String &msg);

		virtual bool handleEvent(Ogre::ScriptCompiler *compiler, Ogre::ScriptCompilerEvent *evt, void *retval);

	private:
		void loadGPKTexture(Ogre::String texturePath,Ogre::String textureName);//Load GPK Texture
	private:
		Ogre::String _materialPath;//material file path
		Ogre::String _parentPath;
	};


	/*Create default materials
	*/
	class GameMaterialManager
	{
	protected:
		//prebuild default material names.
		static const std::string DEFAULT_MATERIAL_NAME;
		static const std::string WHITE_MATERIAL_NAME;
		static const std::string GRAY_MATERIAL_NAME;
		static const std::string DARK_MATERIAL_NAME;
		static const std::string WIREFRAME_MATERIAL_NAME;

		GameMaterialManager();
	public:
		static GameMaterialManager& getSingleton();

		/*Load .material file in .gpk archive,we will try to load file that match .mesh file(have same prefix)
		@param meshName - .mesh file name(path)
		*/
		static void load(Ogre::String meshName);//load .material file

		inline bool hasMaterial(Ogre::String name)
		{
			Ogre::MaterialPtr ptr=Ogre::MaterialManager::getSingleton().getByName(name);
			if(ptr.isNull()){
				return false;
			}
			return true;
		}

		Ogre::MaterialPtr createDefaultMaterial(Ogre::String name);

		/*Force init MaterialManager
		*/
		inline static std::string getDefaultMaterialName()
		{
			return DEFAULT_MATERIAL_NAME;
		}

		inline static std::string getWireFrameMaterialName()
		{
			return WIREFRAME_MATERIAL_NAME;
		}

		inline static std::string getWhiteMaterialName()
		{
			return WHITE_MATERIAL_NAME;
		}

		inline static std::string getGrayMaterialName()
		{
			return GRAY_MATERIAL_NAME;
		}

		inline static std::string getDarkMaterialName()
		{
			return DARK_MATERIAL_NAME;
		}


	private:
		void init();
		Ogre::MaterialPtr createDefaultMaterial();//
		Ogre::MaterialPtr createWireframeMaterial();
	};
}
#define GNgMaterialManager PQEngine::GameMaterialManager::getSingleton()
#endif
